home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / NumTalk ƒ / NumTalk.shar < prev   
Encoding:
Text File  |  1988-11-04  |  9.5 KB  |  371 lines  |  [TEXT/EDIT]

  1. #! /bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #! /bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create the files:
  6. #
  7. #    number.c
  8. #
  9. # This archive created: Tue Oct 18 09:35:23 1988
  10. # By:    Roger L. Long (bytebug@dhw68k.cts.com)
  11. #
  12. export PATH; PATH=/bin:$PATH
  13. echo shar: extracting "'number.c'" '(8687 characters)'
  14. if test -f 'number.c'
  15. then
  16.     echo shar: will not over-write existing file "'number.c'"
  17. else
  18. sed 's/^X//' << \SHAR_EOF > 'number.c'
  19. X/*
  20. X*Program name:  Number Talk
  21. X*
  22. X*Author:  The guts of this program come from an unknown Unix machine.  
  23. X*          There was no documentation, so the author is unknown.  I did
  24. X*          a quick port to the Mac (and Lightspeed C), and added the 
  25. X*          speech feature.  Ted C. Johnson, August 10, 1988.  As far as
  26. X*          I know, the program is Public Domain (FreeWare).  Have fun!
  27. X*
  28. X*Compilation instructions:  use Lightspeed C, v. 2.15.  This program does
  29. X*                            NOT use a resource file.  It was tested on a
  30. X*                            Mac SE HD20, running System/Finder 4.1/5.5.
  31. X*
  32. X*Summary:  This program translates a number (e.g., -123.454) into English 
  33. X*           ("Negative One Hundred Twenty-Three Point Four Five Four"),
  34. X*           and speaks it.  Number Talk handles positive and negative 
  35. X*           integers and floating point numbers, but does not accept commas.
  36. X*
  37. X*           Number Talk will translate the number to either a cardinal 
  38. X*           number (e.g., 4 becomes "Four") or an ordinal number (e.g.,
  39. X*           4 becomes "Fourth".
  40. X*  
  41. X*           Type "o" for ordinal mode.
  42. X*           Type "c" for cardinal mode.
  43. X*           Type "q" to quit.
  44. X*            Type a number, hit carriage return, and Number Talk will
  45. X*           spell it and then speak it.
  46. X*
  47. X*NOTE:  You must have the MacinTalk driver in your System Folder to
  48. X*        run this program!
  49. X*/
  50. X
  51. X#include <stdio.h>
  52. X#include <strings.h>
  53. X#include <MacTypes.h>
  54. X#include <MacinTalk.h>
  55. X
  56. X
  57. X
  58. X#define        TRUE    1
  59. X#define        FALSE    0
  60. X
  61. Xchar words[BUFSIZ];
  62. XStr255 s;
  63. X
  64. XSpeechHandle theSpeech;
  65. XHandle theText;
  66. X
  67. X
  68. X
  69. Xmain(argc,argv)
  70. Xint  argc;
  71. Xchar *argv[];
  72. X{
  73. Xdouble n;                /* Holds number for pass to ftow */
  74. Xchar *numb;                /* Pointer to return from number */
  75. Xint thend;                /* Flag for ordinal numbers */
  76. Xextern char *ftow();
  77. Xextern double atof();
  78. Xint quit = FALSE;
  79. X
  80. X    thend = FALSE;
  81. X    
  82. X    SpeechOn("",&theSpeech);
  83. X    theText = NewHandle(0);
  84. X    
  85. X    printf("Welcome to \"Number Talk\"\n");
  86. X    say("Welcome to Number Talk", FALSE);
  87. X    say("(a public domain program ported by Ted C Johnson)", TRUE);
  88. X    printf("\n");
  89. X    say("Enter any number, and I will spell it and speak it", TRUE);
  90. X    say("Please don't use commas!", TRUE);
  91. X    say("Type c for cardinal mode", TRUE);
  92. X    say("Type o for ordinal mode", TRUE);
  93. X    say("Type q to quit", TRUE);
  94. X    printf("\n");
  95. X    say("Here we go", TRUE);
  96. X    
  97. X    printf("\n\n");
  98. X    
  99. X    for (;!quit;) {
  100. X        say("Enter a number",FALSE);
  101. X        printf("Enter a number (or a command)-->");
  102. X        gets(s);
  103. X        
  104. X        switch(s[0]) {
  105. X            case 'q':
  106. X                quit = TRUE;
  107. X                break;
  108. X                
  109. X            case 'o':
  110. X                thend = TRUE;/*ordinal numbers wanted*/
  111. X                break;
  112. X                
  113. X            case 'c':
  114. X                thend = FALSE;
  115. X                break;
  116. X                
  117. X            default:
  118. X                  n = atof(s);            /* Get a float for ftow */
  119. X                numb = ftow(n,thend);        /* Generate the words */
  120. X                
  121. X                if (n < 0) {
  122. X                    say("negative", FALSE);
  123. X                }
  124. X                
  125. X                say(s, FALSE);
  126. X                say("in words is", FALSE);
  127. X                printf("%s\n",numb);        /* Print it */
  128. X                say(numb, FALSE);
  129. X
  130. X                break;
  131. X            }
  132. X       }/*for*/
  133. X       
  134. X       SpeechOff(theSpeech);
  135. X}
  136. X
  137. X
  138. X
  139. Xsay(s, printit)
  140. XStr255 s;
  141. Xint printit;
  142. X{
  143. X    if (printit) {
  144. X        printf("%s\n", s);
  145. X    }
  146. X    Reader(theSpeech, s, (long)strlen(s), theText);
  147. X    MacinTalk(theSpeech, theText);
  148. X}
  149. X
  150. X/* Table for name of each three-digit group */
  151. Xstatic char *units[] =            
  152. X    {                    
  153. X    " Trillion",
  154. X    " Billion",
  155. X    " Million",
  156. X    " Thousand",
  157. X    "\0\0\0\0\0"
  158. X    };
  159. X    
  160. X    
  161. X    
  162. X/* Names of numbers that are unique */
  163. Xstatic char *numbers[] =        
  164. X    {
  165. X    "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
  166. X    "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
  167. X    "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty",
  168. X    "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
  169. X    };
  170. X    
  171. X    
  172. X    
  173. X/* Ordinal number coding table */
  174. Xstatic char *ord[] =            
  175. X    {
  176. X    "+th","First","Second","Third","+th","Fifth","+th","+th","+h",
  177. X    "Ninth","+th","+th","+th","+th","+th","+th","+th","+th","+th","+th"
  178. X    };
  179. X
  180. X
  181. X
  182. X/*
  183. X*Routine to convert the number to words
  184. X*Entry:
  185. X*x = double precision number to convert
  186. X*ordflag = do you want ordinal numbers? (0 = no, !0 = yes)
  187. X*Returns:
  188. X*A character pointer to the words
  189. X*/
  190. Xchar *ftow(x,ordflag)
  191. Xdouble x;
  192. Xint ordflag;
  193. X{
  194. Xregister int i;                /* Loop counter */
  195. Xchar numb[25];                /* Holds printf'ed number */
  196. Xchar hold[30];                /* Gets 3 digit grouping */
  197. Xint negflag = FALSE;            /* Is number negative? */
  198. Xint n;                    /* All around number */
  199. X
  200. Xextern void thcon();            /* Convert each thousands group */
  201. X
  202. X    words[0] = '\0';            /* Initialize for strcat */
  203. X    
  204. X    /* More than one quadrillion */
  205. X    if (x >= 1e15) {
  206. X        strcpy(words,"Overflow");
  207. X        return(words);
  208. X      }
  209. X      
  210. X    /* Just tack "Negative" on, */
  211. X    if (x < 0) {
  212. X        strcpy(words,"Negative ");
  213. X        x = -x;                /*  and convert the positive */
  214. X        negflag = TRUE;            /* But let rest of the routine know */
  215. X    }
  216. X
  217. X    sprintf(numb,"%23.7f",x);        /* Put number into printable form */
  218. X    for (i = 0; numb[i] == ' '; ++i) {    /* Tack on leading zeros */
  219. X        numb[i] = '0';
  220. X    }
  221. X    
  222. X    
  223. X    if (x < 1) {
  224. X        strcat(words,numbers[0]);        /* Add a "Zero" if it is less than 1 */
  225. X    }
  226. X    else {
  227. X        for (i = 0; i < 5; i++)    {    /* Loop through each thousands group */
  228. X            sscanf(&numb[i*3],"%3d",&n);    /* Get number less than one thousand */
  229. X            thcon(hold,n);            /* Convert it */
  230. X            
  231. X            /* If it isn't zero */
  232. X            if (*hold != '\0') {
  233. X                if (words[0] != '\0') {    /* If it isn't the first word */
  234. X                    if (!negflag)        /* If the last word wasn't "Negative" */
  235. X                    strcat(words,", "); /* Add a comma */
  236. X                    strcat(words,hold);    /* Then add the words */
  237. X                    negflag = FALSE;    /* No more "Negative" */
  238. X                }
  239. X            else {
  240. X                strcpy(words,hold);    /* Use copy if it is the first word */
  241. X            }
  242. X            strcat(words,units[i]);    /* And tack on the "Million", etc */
  243. X            }
  244. X    }
  245. X    }
  246. Xsscanf(&numb[16],"%d",&n);        /* Check for stuff after the decimal */
  247. Xif (n != 0)                /* If there is stuff */
  248. X    {
  249. X    strcat(words," Point");        /* Add decimal point */
  250. X    for (i = 16; numb[i] != '\0'; i++)    /* Get to end of number */
  251. X    ;
  252. X    i--;
  253. X    while (numb[i] == '0')        /* Strip off trailing zeros */
  254. X    i--;
  255. X    numb[i+1] = '\0';
  256. X    for (i= 16; numb[i] != '\0'; i++)    /* Pull off one digit at a time */
  257. X    {
  258. X    strcat(words," ");        /* Add the space */
  259. X    n = numb[i] - '0';        /* And convert to decimal */
  260. X    strcat(words,numbers[n]);    /* Tack on the right number */
  261. X    }
  262. X    }
  263. Xelse                    /* If there ain't no decimals */
  264. X    {
  265. X    if (ordflag)            /* And you want ordinals */
  266. X    {
  267. X    for (i = 0; words[i] != '\0'; ++i)  /* Get to end of words */
  268. X        ;
  269. X    i--;
  270. X    if (words[i] == 'y')        /* If it is a "Twenty", etc */
  271. X        {
  272. X        words[i] = '\0';        /* Change the "y" to "ieth" */
  273. X        strcat(words,"ieth");
  274. X        }
  275. X    else                /* Search for beginning of last word */
  276. X        {
  277. X        while(words[i-1] != ' ' && words[i-1] != '-' && i > 0)
  278. X        i--;
  279. X        for (n = 0; n < 20; n++)    /* Find out what the last word is */
  280. X        if (strcmp(&words[i],numbers[n]) == 0)
  281. X            break;
  282. X        if (n > 19)            /* If we can't figure out what it is */
  283. X        strcat(words,"th");    /*  just add a "th" */
  284. X        else
  285. X        {
  286. X        if (ord[n][0] == '+')    /* Plus = cat the rest of the string */
  287. X            strcat(words,&ord[n][1]);
  288. X        else            /* Otherwise make an entire replace */
  289. X            {
  290. X            words[i] = '\0';
  291. X            strcat(words,ord[n]);
  292. X            }
  293. X        }
  294. X        }
  295. X    }
  296. X    }
  297. X
  298. Xfor (n = 0; ; n = i)            /* Divide words up into < 80 byte */
  299. X    {                    /*  sections separated by a newline */
  300. X    for (i = n; i < n+80; ++i)
  301. X    if (words[i] == '\0')
  302. X        return(words);
  303. X    while (words[i] != ' ')
  304. X    --i;
  305. X    words[i] = '\n';
  306. X    }
  307. X}
  308. X
  309. X
  310. X
  311. X/*
  312. X*Routine to convert a number less than one thousand into words.  Basic
  313. X*routine, because all groups of three digits similar.
  314. X*Entry:
  315. X*buf = a place to put the converted number
  316. X*z = the number to convert
  317. X*Return:
  318. X*Nothing
  319. X*/
  320. X
  321. Xvoid thcon(buf,z)
  322. Xregister int z;
  323. Xchar buf[];
  324. X{
  325. Xregister int d;                /* The divided down number */
  326. Xregister int spflag = FALSE;        /* Do we need a space catted? */
  327. X
  328. X    buf[0] = '\0';    /* Initialize */
  329. X    
  330. X     /* Converting zero is easy */
  331. X    if (z != 0) {
  332. X        d = z / 100; /* Find out if we need and hundreds */
  333. X        
  334. X        if (d != 0){
  335. X            strcat(buf,numbers[d]);     /* Tack them on */
  336. X            strcat(buf," Hundred");
  337. X            spflag = TRUE;            /* Need a space afterward */
  338. X        }
  339. X
  340. X            z %= 100;                /* The < 100 stuff */
  341. X             /* Is there any? */
  342. X        if (z != 0)     {
  343. X            if (spflag)    {        /* Need a separator */
  344. X                strcat(buf," ");
  345. X            }
  346. X            /* Simple "Forty-Four" type construct */
  347. X            if (z > 19)     {
  348. X                    d = z / 10 + 18;        /* Get the "Forty" part into d */
  349. X                z %= 10;            /* Get the "Four" part into z */
  350. X                strcat(buf,numbers[d]); /* Cat the stuff */
  351. X                if (z != 0) {
  352. X                strcat(buf,"-");
  353. X                strcat(buf,numbers[z]);
  354. X                }
  355. X            }
  356. X            else {                /* Just use "One" to "Nineteen" */
  357. X                strcat(buf,numbers[z]);
  358. X            }
  359. X        }
  360. X    }
  361. X    return;
  362. X}
  363. SHAR_EOF
  364. if test 8687 -ne "`wc -c < 'number.c'`"
  365. then
  366.     echo shar: error transmitting "'number.c'" '(should have been 8687 characters)'
  367. fi
  368. fi # end of overwriting check
  369. #    End of shell archive
  370. exit 0
  371.